<template>
  <div
      class="switch-container"
      :class="[
      `switch-${effectiveSize}`,
      { 'is-disabled': disabled },
      { 'is-checked': isChecked }
    ]"
      :style="customSizeStyle"
      @click="toggleSwitch"
  >
    <input
        type="checkbox"
        :name="name"
        :id="id"
        class="switch-input"
        :disabled="disabled"
        :checked="isChecked"
        @change="handleInput"
    >
    <div class="switch-core">
      <div class="switch-inner">
        <span v-if="isChecked" class="on-content">
          <i v-if="onIcon" :class="onIcon"></i>
          <span v-if="onText">{{ onText }}</span>
        </span>
        <span v-else class="off-content">
          <i v-if="offIcon" :class="offIcon"></i>
          <span v-if="offText">{{ offText }}</span>
        </span>
      </div>
      <div class="switch-button"></div>
    </div>
  </div>
</template>

<script setup>
import { computed } from 'vue'

const props = defineProps({
  modelValue: {
    type: [Boolean, String, Number],
    default: false
  },
  disabled: {
    type: Boolean,
    default: false
  },
  size: {
    type: String,
    default: 'default',
    validator: (value) => ['small', 'default', 'large'].includes(value) || /^\d+px$/.test(value)
  },
  onIcon: String,
  onText: String,
  onValue: {
    type: [Boolean, String, Number],
    default: true
  },
  offIcon: String,
  offText: String,
  offValue: {
    type: [Boolean, String, Number],
    default: false
  },
  name: String,
  id: String
})

const emit = defineEmits(['update:modelValue', 'change'])

const isChecked = computed(() => {
  return props.modelValue === props.onValue
})

const effectiveSize = computed(() => {
  return ['small', 'default', 'large'].includes(props.size)
      ? props.size
      : 'custom'
})

const customSizeStyle = computed(() => {
  if (props.size.match(/^\d+px$/)) {
    const size = props.size.replace('px', '')
    return {
      '--switch-width': `${size * 2}px`,
      '--switch-height': `${size}px`,
      '--button-size': `${size - 8}px`
    }
  }
  return null
})

const toggleSwitch = () => {
  if (props.disabled) return
  const newValue = isChecked.value ? props.offValue : props.onValue
  emit('update:modelValue', newValue)
  emit('change', newValue)
}

const handleInput = (e) => {
  const newValue = e.target.checked ? props.onValue : props.offValue
  emit('update:modelValue', newValue)
  emit('change', newValue)
}
</script>

<style scoped>
.switch-container {
  position: relative;
  display: inline-block;
  vertical-align: middle;
}

.switch-input {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
  margin: 0;
}

.switch-core {
  position: relative;
  display: block;
  border-radius: 16px;
  background-color: #dcdfe6;
  transition: background-color 0.3s;
  cursor: pointer;
}

.switch-core:hover {
  background-color: #c0c4cc;
}

.switch-button {
  position: absolute;
  top: 4px;
  left: 4px;
  border-radius: 50%;
  background-color: #fff;
  transition: all 0.3s;
  box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}

.switch-inner {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  color: #fff;
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
}

/* 默认尺寸 */
.switch-default {
  --switch-width: 60px;
  --switch-height: 32px;
  --button-size: 24px;
}

.switch-default .switch-core {
  width: var(--switch-width);
  height: var(--switch-height);
}

.switch-default .switch-button {
  width: var(--button-size);
  height: var(--button-size);
}

/* 小尺寸 */
.switch-small {
  --switch-width: 48px;
  --switch-height: 24px;
  --button-size: 16px;
}

/* 大尺寸 */
.switch-large {
  --switch-width: 72px;
  --switch-height: 40px;
  --button-size: 32px;
}

/* 自定义尺寸 */
.switch-custom .switch-core {
  width: var(--switch-width);
  height: var(--switch-height);
}

.switch-custom .switch-button {
  width: var(--button-size);
  height: var(--button-size);
}

/* 选中状态 */
.is-checked .switch-core {
  background-color: #409eff;
}

.is-checked .switch-core:hover {
  background-color: #66b1ff;
}

.is-checked .switch-button {
  left: calc(100% - var(--button-size) - 4px);
}

/* 禁用状态 */
.is-disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.on-content,
.off-content {
  display: flex;
  align-items: center;
  height: 100%;
  padding: 0 8px;
}

.on-content {
  justify-content: flex-start;
}

.off-content {
  justify-content: flex-end;
}
</style>